﻿using Apex.Commons;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Unicode;

namespace System
{
    public static class JsonExtentions
    {
        // 创建一个静态的 JavaScript 编码器，用于在 JSON 序列化过程中处理特殊字符的编码
        //如果配置中不设置这个，那么 汉字部分 就输出这样的格式："\u96C5\u601D\u771F\u9898"
        public readonly static JavaScriptEncoder Encoder = JavaScriptEncoder.Create(UnicodeRanges.All);

        public static JsonSerializerOptions CreateJsonSerializerOptions(bool camelCase = false)
        {
            JsonSerializerOptions opt = new JsonSerializerOptions { Encoder = Encoder };
            if (camelCase)
            {
                opt.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase;
                opt.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
            }
            opt.Converters.Add(new DateTimeJsonConverter("yyyy-MM-dd HH:mm:ss"));
            return opt;
        }

        /// <summary>
        /// 将对象序列化为 JSON 格式的字符串
        /// </summary>
        /// <param name="value">要序列化的对象</param>
        /// <param name="camelCase">指定是否使用驼峰命名约定</param>
        /// <returns>序列化后的 JSON 格式的字符串</returns>
        public static string ToJsonString(this object value, bool camelCase = false)
        {
            var options = new JsonSerializerOptions
            {
                // 设置是否使用驼峰命名约定
                PropertyNamingPolicy = camelCase ? JsonNamingPolicy.CamelCase : null,
                // 设置格式化输出
                WriteIndented = true,
                // 使用之前定义的 Encoder 字段设置 JSON 序列化的编码器，保证汉字能够符合预期输出（转义正常）
                Encoder = Encoder
            };
            return JsonSerializer.Serialize(value, value.GetType(), options);
        }

        /// <summary>
        /// 尝试将 JSON 格式的字符串反序列化为指定类型的对象
        /// </summary>
        /// <typeparam name="T">要反序列化的对象的类型</typeparam>
        /// <param name="value">要反序列化的 JSON 格式的字符串</param>
        /// <returns>反序列化后的对象</returns>
        public static T? ParseJson<T>(this string value)
        {
            if (string.IsNullOrWhiteSpace(value))
            {
                return default(T);
            }
            var options = CreateJsonSerializerOptions();
            return JsonSerializer.Deserialize<T>(value, options);
        }
    }
}
